using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content;
using System.Xml;
using System.Collections;
using Microsoft.Xna.Framework.Graphics;
using Dracham.TileManagement.CharacterManagement;
using Dracham.Classes;
using Microsoft.Xna.Framework;

namespace Dracham.TileManagement
{
    public class Zone
    {
        private String zoneName;
        private String zoneId;
        private Int32 height;
        private Int32 width;
        private ContentManager content;

        private List<ZoneTile> zoneTiles;
        private Hashtable textures;
        private List<MobileObject> mobileObjects;

        private Zone(XmlNode zoneNode)
        {
            this.textures = new Hashtable();
            this.mobileObjects = new List<MobileObject>();

            XmlDocument doc = new XmlDocument();
            this.zoneName = zoneNode.Attributes["Name"].Value;
            this.zoneId = zoneNode.Attributes["Id"].Value;
            this.width = Convert.ToInt32(zoneNode.Attributes["Width"].Value);
            this.height = Convert.ToInt32(zoneNode.Attributes["Height"].Value);
            this.zoneTiles = new List<ZoneTile>();

            foreach (XmlNode obj in zoneNode.ChildNodes)
            {
                if (obj.Name == "ZoneTile")
                {
                    this.zoneTiles.Add(new ZoneTile(obj, this));
                }
            }
        }

        public void ReleaseZone()
        {
            textures.Clear();
        }

        #region properties

        public String ZoneName
        {
            get { return zoneName; }
        }

        public String ZoneId
        {
            get { return zoneId; }
        }

        #endregion

        internal void LoadTexture(string source)
        {
            if (!textures.ContainsKey(source))
                textures.Add(source, content.Load<Texture2D>(source));
        }

        internal Microsoft.Xna.Framework.Graphics.Texture2D GetTexture(string source)
        {
            return (Texture2D)textures[source];
        }

        internal void EnterZone()
        {

        }

        internal void Render(SpriteBatch spriteBatch,GameTime gameTime,  Player player)
        {
            //
            // calc center
            Int32 x2 = Dracham.Width / 2;
            Int32 y2 = Dracham.Height / 2;

            //
            // current player pos
            Int32 posx = player.Position.MapX; // 0
            Int32 posy = player.Position.MapY; // 0

            //
            // lower
            Int32 posxm = posx-6 + Dracham.Width;
            Int32 posym = posy-6 + Dracham.Height;

            this.zoneTiles.ForEach(delegate(ZoneTile zo)
            {
                if (zo.DestX >= (posx - 7) && zo.DestX <= posxm &&
                    zo.DestY >= (posy - 7) && zo.DestY <= posym)
                {
                    zo.Render(spriteBatch, posx, posy, player.Position.TileX, player.Position.TileY, player);
                }
            });

            this.mobileObjects.ForEach(delegate(MobileObject mo)
            {
                if (mo.Position.MapX >= (posx - 7) && mo.Position.MapX <= posxm &&
                    mo.Position.MapY >= (posy - 7) && mo.Position.MapY <= posym)
                {
                    mo.Render(spriteBatch, gameTime, posx, posy, player.Position.TileX, player.Position.TileY, player);
                }
            });
        }

        internal void Update()
        {
            //throw new Exception("The method or operation is not implemented.");
        }

        public Boolean IsCollision(Int32 x, Int32 y)
        {
            if (x < 0 || y < 0)
                return true;

            if (x >= this.width || y >= this.height)
                return true;

            ZoneTile obj = this.zoneTiles.Find(delegate(ZoneTile zo)
            {
                if (zo.DestX == x && zo.DestY == y)
                    return true;

                return false;
            });

            if (obj == null)
                return false;

            return obj.Solid;
        }

        public void UpdateMobileObject(String mobId, String modelId, String zoneId, Int32 fx, Int32 fy, Int32 tx, Int32 ty)
        {
            MobileObject mo = this.mobileObjects.Find(delegate(MobileObject m)
            {
                return m.MobId == mobId;
            });

            if (mo == null)
            {
                mo = new MobileObject(mobId, modelId, new Position(fx, fy, zoneId), new Position(tx, ty, zoneId));
                this.mobileObjects.Add(mo);
            }
            else
            {
                mo.UpdatePosition(tx, ty, fx, fy);
            }
        }

        public static Zone FromXmlNode(XmlNode zone)
        {
            return new Zone(zone);
        }

        public MobileObject GetSelectedMobileObject()
        {
            foreach (MobileObject mo in this.mobileObjects)
            {
                if (mo.IsMarked)
                    return mo;
            }

            return null;
        }

        public void RemoveMobileObject(string mobId)
        {
            MobileObject mo = this.mobileObjects.Find(delegate(MobileObject m)
            {
                return m.MobId == mobId;
            });

            if (mo != null)
            {
                mo.IsDead = true;
            }
        }
    }
}
